iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
0
Modern Web

跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset系列 第 14

[day13] YDKJS (Scope) : JavaScript 是 parser language ? 不是 interpreter 嗎?

  • 分享至 

  • xImage
  •  
  • 廢話前言
    終於來到 Scope !!!!!
  • 這邊預計會講的順序是 : lexical scope -> Closure -> Modules

開始以前,先讀一下 YDKJS: types & grammar/ch5.md

在這邊你會學習到接下來不斷提到的東西 :

  • Statements & Expressions
  1. declaration ( declaration statement )
  2. expression (assignment expressions、expression statement)
  • Contextual Rules 的 { .. } Curly Braces
[] + {}; // "[object Object]" 
// 這個是 coercion 型別轉換的例子 , 轉成 "" + "[object Object]" ==> "[object Object]"

{} + []; // 0  
// 前面的 {} 其實沒有被讀到(empty block),所以是一元運算子的轉數字 +[] ==> 0

其他狀況自己看書 YDKJS ch5.md#contextual-rules

舉例來說 :

variable-statement Spec.

這邊之後我不太讀文件了,文件到這邊只是規範,具體實作就比較難理解。
(資質不好 QQ)
舉個書上例子

  • Statement Completion Values
    我認為這部分只要了解兩個東西的差別:
  1. Declaration 完成的回傳值,通常是 undefined。
    // var a; var b;
    • declaration statements 依然是 Declaration 為主 ,有錯請告知我~
      var a = 10
  2. Expressions 完成的回傳值,通常是 Expressions return 的值。
    b = 2; a = b + 2

可以去玩看看 JavaScript ast 產生器,圖像配合書,理解更快喔。


Scope: Where to looking for things?

你可能在書上面看過這個段落

簡體 ch1.md#引擎作用域对话

function foo(a) {
	console.log( a ); // 2
}

foo( 2 );

Engine: 嗨 Scope, 我有一個 RHS reference 是 foo. 你有聽說過嗎?

Scope: Why yes, 我有. Compiler 在幾秒之前剛剛 declared 他. 他是一個 function. Here you go.

Engine: Great, thanks! OK, I'm executing foo.

Engine: 嗨, Scope, 我有一個 LHS reference 是 a, 你有聽說過嗎?

Scope: Why yes, 我有. Compiler 在幾秒之前剛剛 declared 他, 他是一個 formal parameter to foo. Here you go.

Engine: Helpful as always, Scope. Thanks again. Now, time to assign 2 to a.

Engine: 嗨, Scope, 抱歉打擾. 我需要一個 RHS look-up for console. 你有聽說過嗎?

Scope: No problem, Engine,沒關係 這是我應該做的. Yes, 我有 console. 他是內建的(built-in). Here ya go.

Engine: Perfect. Looking up log(..). OK, great, it's a function.

Engine: Yo, Scope. 你可以幫我找 RHS reference to a. 我想我還記得他, 不過我想二次確認。

Scope: You're right, Engine. 同一個 a , 他沒改變. Here ya go.

Engine: Cool. Passing the value of a, which is 2, into log(..).

...

看起來很ㄎㄧㄤ,明天再來詳細描述。
開始以前,請先想像 declaration 像是 可以塗顏色的小球(marble),
作用域(Scope) 像是有顏色的桶子,
然後 引擎(Engine) 負責玩丟球遊戲,把有顏色的桶子和球配對。

我們要做的就是模仿他們溝通,玩這個把一樣顏色的小球丟到一樣顏色的桶子的遊戲。

Kyle Simpson : 網路上可以找到最像的圖。

不過還有一件事要說 ...

JavaScript 是 parsed language ???

一般常見的定義,會看到大家說 "dynamic" or "interpreted" languages。
但其實多數人會誤解像是 bash 一樣 一行一行執行,由上到下的 "interpreter"。

但是事實上,如同其他多數的 language-compiler, JavaScript 會執行以下階段

可以去玩看看 JavaScript ast 產生器,圖像配合書,理解更快喔。

  1. Tokenizing/Lexing

  2. Parsing

    同上圖,這邊產生的 tree 結構叫做 "AST" (Abstract Syntax Tree).

    這些步驟都是一直產生的,具體應用大家有寫過 JavaScript/TypeScript 應該很常用

    你可能發現一個規則,這些東西都是寫 code 才有用,真正上線都會移掉。
    背後原因就是 AST 。

    更細節的 AST 可以玩看看這個工具,不過我覺得上面那個就很夠了。
    https://astexplorer.net/

    這個比較偏向如果想自己寫 ESlint 規則

    • variable declaration can have multiple declarators

    • function 裡面有 block statement,block statement 可以放 expression statement 和 return statement,當然也可以放 variable declaration

    • identifier , experssion 有左右之分

    • 通常左邊是 identifier,右邊是 experssion or literal

    • 你應該想到了,我們常常說的 LHS、RHS 的 L、R 就是這邊的左右

    • 但其實不是方向的「左」「右」,是取決於有沒有 target

      • 你不能把 identifier 放在右邊 ,如果「能」請告訴我 QQ
      • 事實上只有 LHS ,一般來說表示有 target : retrieve source (value)
      • 不是 LHS 的全部都是 RHS ,也就是說,沒有 target 就是 source

      有一點 ( a && b ) 運算子 或是 (a || b) 運算子 只在乎 a 的味道。

  3. Code-Generation : bytecode。

(有問題或是不清楚的地方,或是有其他資源可以補充給我~)

放棄 interpreter 的 mindset,我們才會拉回來說球和桶子的遊戲

如果還不能接受 JavaScript 會提前 parse,多玩一下上面的 AST,找資料理解一下怎麼產生的。

  1. 我們在模仿 Engine 和 Scope ,其實就是抽象化 AST 的結果
  2. identifier 就是我們的小球
  3. Scope 就是我們的桶子
  4. 我們會把球和桶子塗上顏色,然後把球(identifier)丟到顏色對應的桶子(Scope)裡 。
  5. units of scope : function , blocks
  6. 這時候還沒有 bytecode ,但我們已經建立好 lexical environment 了 (reference: EC)。

Summary : JavaScript 是 two-pass System

1. AST 物件產生(parsed)會在執行前完成, 其實只有給定 declaration,作用域(Scope)。

2. executable code(bytecode)才有逐行執行

3. Hoisting 並不存在,那只是為了強行解釋 JavaScript 是 interpreter 這個很容易誤解的說法用的名詞

(所以你不要誤認 JavaScript 是 interprete, JavaScript 會提前 parsed AST)
你可以查文件(ECMA-262, 10th edition, June 2019),Hoisting 這個字並沒有任何解釋。

個人註解:明天再補上具體範例,偷一下天數 XD ,如果有問題可以先討論


上一篇
[day12] YDKJS (Equality) : 不論任何 Equality,你應該「總是知道」型別。來做相等性 Cases 練習吧!
下一篇
[day14] YDKJS (Scope) : 執行環境 (Execution Context)的角色扮演遊戲(compile time篇)
系列文
跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言